package com.forest.datachangetracker.service.audit.impl;

import cn.hutool.core.util.ObjectUtil;
import com.forest.datachangetracker.annotation.DataAudit;
import com.forest.datachangetracker.context.AuditContext;
import com.forest.datachangetracker.enums.OperationType;
import com.forest.datachangetracker.service.audit.AuditStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Collection;

@Slf4j
@Component
public class BatchOperationAuditStrategy implements AuditStrategy {

    @Override
    public boolean supports(DataAudit dataAudit) {
        return dataAudit.multipleEntities() && !dataAudit.entitiesExpression().isEmpty();
    }

    @Override
    public void execute(AuditContext context, Object result, DataAudit dataAudit, Object oldEntity) {
        try {
            // 解析实体集合表达式
            Collection<?> entities = context.getSpelParser().parseExpression(dataAudit.entitiesExpression())
                    .getValue(context.getEvaluationContext(), Collection.class);

            if (entities != null) {
                String batchId = generateBatchId(context, dataAudit);

                for (Object entity : entities) {
                    AuditContext entityContext = context.copy();
                    entityContext.setBatchId(batchId);

                    // 处理单个实体审计
                    if(ObjectUtil.equals(dataAudit.operationType(), OperationType.DELETE)) {
                        processChanges(entityContext, null, entity, dataAudit);
                    } else if(ObjectUtil.equals(dataAudit.operationType(), OperationType.CREATE)  || ObjectUtil.equals(dataAudit.operationType(), OperationType.UPDATE)) {
                        //批量操作，只处理新值
                        processChanges(entityContext, entity, null, dataAudit);
                    }

                }
            }

        } catch (Exception e) {
            log.error("批量操作审计策略执行失败", e);
            context.getAuditLogService().recordAuditLog(
                    context, null, null, null, false, e.getMessage()
            );
        }
    }

}
